package com.google.code.p.narcissus.ui.listeners;

import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;

import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.event.MouseInputAdapter;

public class TestClass {
	 JLabel label;
	    static String starFile = "images/starfield.gif";
	    
	    private void buildUI(Container container) {
	        container.setLayout(new BoxLayout(container,
	                                          BoxLayout.PAGE_AXIS));
	                                          
	        SelectionArea area = new SelectionArea( this);
	        container.add(area);

	        label = new JLabel("Drag within the image.");
	        label.setLabelFor(area);
	        container.add(label);

	        //Align the left edges of the components.
	        area.setAlignmentX(Component.LEFT_ALIGNMENT);
	        label.setAlignmentX(Component.LEFT_ALIGNMENT); //redundant
	        container.setSize(600,800);
	    }

	    public void updateLabel(Rectangle rect) {
	        int width = rect.width;
	        int height = rect.height;

	        //Make the coordinates look OK if a dimension is 0.
	        if (width == 0) {
	            width = 1;
	        }
	        if (height == 0) {
	            height = 1;
	        }

	        label.setText("Rectangle goes from ("
	                      + rect.x + ", " + rect.y + ") to ("
	                      + (rect.x + width - 1) + ", "
	                      + (rect.y + height - 1) + ").");
	    }

	    /** Returns an ImageIcon, or null if the path was invalid. */
	    protected static ImageIcon createImageIcon(String path) {
	        java.net.URL imgURL = TestClass.class.getResource(path);
	        if (imgURL != null) {
	            return new ImageIcon(imgURL);
	        } else {
	            System.err.println("Couldn't find file: " + path);
	            return null;
	        }
	    }

	    /**
	     * Create the GUI and show it.  For thread safety, 
	     * this method should be invoked from the 
	     * event-dispatching thread.
	     */
	    private static void createAndShowGUI() {
	        //Create and set up the window.
	        JFrame frame = new JFrame("SelectionDemo");
	        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

	        //Set up the content pane.
	        TestClass controller = new TestClass();
	        controller.buildUI(frame.getContentPane());

	        //Display the window.
	        frame.setSize(800,600);
	        frame.setVisible(true);
	    }

	    public static void main(String[] args) {
	        //Schedule a job for the event-dispatching thread:
	        //creating and showing this application's GUI.
	        javax.swing.SwingUtilities.invokeLater(new Runnable() {
	            public void run() {
	                createAndShowGUI(); 
	            }
	        });
	    }
	    
	    private class SelectionArea extends JPanel {
	        Rectangle currentRect = null;
	        Rectangle rectToDraw = null;
	        Rectangle previousRectDrawn = new Rectangle();
	        TestClass controller;
	    
	        public SelectionArea(TestClass controller) {
	            super(); //This component displays an image.
	            setSize(100,100);
	            this.controller = controller;
	            setOpaque(true);
	            setMinimumSize(new Dimension(10,10)); //don't hog space
	    
	            MyListener myListener = new MyListener();
	            addMouseListener(myListener);
	            addMouseMotionListener(myListener);
	        }
	    
	        private class MyListener extends MouseInputAdapter {
	            public void mousePressed(MouseEvent e) {
	                int x = e.getX();
	                int y = e.getY();
	                currentRect = new Rectangle(x, y, 0, 0);
	                updateDrawableRect(getWidth(), getHeight());
	                repaint();
	            }
	    
	            public void mouseDragged(MouseEvent e) {
	                updateSize(e);
	            }
	    
	            public void mouseReleased(MouseEvent e) {
	                updateSize(e);
	            }
	    
	            /* 
	             * Update the size of the current rectangle
	             * and call repaint.  Because currentRect
	             * always has the same origin, translate it
	             * if the width or height is negative.
	             * 
	             * For efficiency (though
	             * that isn't an issue for this program),
	             * specify the painting region using arguments
	             * to the repaint() call.
	             * 
	             */
	            void updateSize(MouseEvent e) {
	                int x = e.getX();
	                int y = e.getY();
	                currentRect.setSize(x - currentRect.x,
	                                    y - currentRect.y);
	                updateDrawableRect(getWidth(), getHeight());
	                Rectangle totalRepaint = rectToDraw.union(previousRectDrawn);
	                repaint(totalRepaint.x, totalRepaint.y,
	                        totalRepaint.width, totalRepaint.height);
	            }
	        }
	    
	        protected void paintComponent(Graphics g) {
	            super.paintComponent(g); //paints the background and image
	    
	            //If currentRect exists, paint a box on top.
	            if (currentRect != null) {
	                //Draw a rectangle on top of the image.
	                g.setXORMode(Color.white); //Color of line varies
	                                           //depending on image colors
	                g.drawRect(rectToDraw.x, rectToDraw.y, 
	                           rectToDraw.width - 1, rectToDraw.height - 1);
	    
	                controller.updateLabel(rectToDraw);
	            }
	        }
	    
	        private void updateDrawableRect(int compWidth, int compHeight) {
	            int x = currentRect.x;
	            int y = currentRect.y;
	            int width = currentRect.width;
	            int height = currentRect.height;
	    
	            //Make the width and height positive, if necessary.
	            if (width < 0) {
	                width = 0 - width;
	                x = x - width + 1; 
	                if (x < 0) {
	                    width += x; 
	                    x = 0;
	                }
	            }
	            if (height < 0) {
	                height = 0 - height;
	                y = y - height + 1; 
	                if (y < 0) {
	                    height += y; 
	                    y = 0;
	                }
	            }
	    
	            //The rectangle shouldn't extend past the drawing area.
	            if ((x + width) > compWidth) {
	                width = compWidth - x;
	            }
	            if ((y + height) > compHeight) {
	                height = compHeight - y;
	            }
	          
	            //Update rectToDraw after saving old value.
	            if (rectToDraw != null) {
	                previousRectDrawn.setBounds(
	                            rectToDraw.x, rectToDraw.y, 
	                            rectToDraw.width, rectToDraw.height);
	                rectToDraw.setBounds(x, y, width, height);
	            } else {
	                rectToDraw = new Rectangle(x, y, width, height);
	            }
	        }
	    }
}
